import wx
import os
import sys
from collections import OrderedDict
import subprocess
import tempfile
import winreg


class AutoPip:
    def __init__(self):
        self.cf = {
            '-i': True,
            'uninstall': False,
            'srsaddr': 'https://pypi.tuna.tsinghua.edu.cn/simple',
            'defaut': ['wxpython', 'numpy', 'matplotlib', 'pandas', 'asammdf',
                       'pyserial', 'canlib', 'pypiwin32']
        }
        self.app = wx.App()
        self.gui = MainFrame(mobj=self)
        # sys.stdout = self.gui.text_log
        # sys.stderr = self.gui.text_log

    def setup(self):
        SetupWin(None, mobj=self)

    def setcf(self, item, value):
        self.cf[item] = value

    def pipinstall(self, packlist):
        packlist = [x.strip() for x in packlist if x.strip()]
        if packlist:
            pippath = self.getpippath()
            if pippath:
                assert os.path.exists(pippath), '--- 找不到 "%s" !!! ---' % pippath
                # tempdir = tempfile.TemporaryDirectory()
                # temppath = os.path.join(tempdir.name, 'temp')
                temp0 = [pippath]
                command = 'uninstall' if self.cf['uninstall'] else 'install'
                temp0 += [command]
                if self.cf['uninstall']: temp0.append('-y')
                if self.cf['-i'] and not self.cf['uninstall']: temp0.append('-i %s' % self.cf['srsaddr'])
                for pack in packlist:
                    print('%s "%s" ...' % (command, pack))
                    # with open(temppath, mode='w') as f:
                    #     fileno = f.fileno()
                    temp1 = temp0 + [pack]
                    a = subprocess.Popen(' '.join(temp1),  # stdout=fileno, stderr=fileno,
                                         stdin=subprocess.DEVNULL, shell=True)
                    a.wait()
                    # with open(temppath, mode='r') as f:
                    #     print(f.read())
                    # sys.stdout.flush()
                # tempdir.cleanup()

    @staticmethod
    def getpippath():

        def getRegeditPythonItem(*rootitems):
            for rootitem in rootitems:
                try:
                    key = winreg.OpenKey(rootitem, r'Software\Python\PythonCore')
                except FileNotFoundError:
                    yield None
                else:
                    yield key

        pykeys = [x for x in getRegeditPythonItem(winreg.HKEY_CURRENT_USER, winreg.HKEY_LOCAL_MACHINE) if x]
        pypaths = []
        for key in pykeys:
            subkeynum, _, __ = winreg.QueryInfoKey(key)
            if subkeynum:
                i = 0
                while True:
                    try:
                        subkeystr = winreg.EnumKey(key, i)
                    except OSError:
                        break
                    else:
                        try:
                            temp = winreg.QueryValue(key, '%s\\InstallPath' % subkeystr)
                        except:
                            pass
                        else:
                            pypaths.append(temp)
                    i += 1

        pypaths = list(set(pypaths))
        if len(pypaths) > 1:
            with AlertUserChsePythonWin(items=pypaths) as chsewin:
                index = chsewin.ShowModal()
            pypath = pypaths[index]
        elif len(pypaths) == 1:
            pypath = pypaths[0]
        else:
            pypath = wx.dirpath = wx.DirSelector(parent=None, message='没有找到Python,请选择Python.exe所在的目录')
        print(pypaths)

        if pypath:
            print('Python Path: "%s"'%pypath)
            return os.path.join(pypath,'Scripts','pip.exe')
        else:
            return ''


class MainFrame(wx.Frame):
    def __init__(self, mobj):
        wx.Frame.__init__(self, None, title='AutoPip', size=(700, 600))
        self.mobj = mobj

        self.SetMenuBar(MainFrameMenuBar(mobj=mobj))

        self.pl = wx.Panel(self, size=(700, 600))

        self.text = wx.TextCtrl(self.pl, style=wx.TE_MULTILINE | wx.TE_DONTWRAP)
        self.text_log = wx.TextCtrl(self.pl, style=wx.TE_MULTILINE | wx.TE_READONLY | wx.TE_DONTWRAP, size=(100, 100))
        self.bt = wx.Button(self.pl, label='开始', size=(80, 40))

        self.sizer = wx.GridBagSizer(5, 5)
        self.sizer.Add(self.text, pos=(0, 0), span=(2, 1), flag=wx.EXPAND | wx.ALL, border=10)
        self.sizer.Add(self.bt, pos=(1, 1), span=(1, 1), flag=wx.ALL, border=10)
        self.sizer.Add(self.text_log, pos=(2, 0), span=(1, 2), flag=wx.EXPAND | wx.ALL, border=10)

        self.sizer.AddGrowableCol(0)
        self.sizer.AddGrowableRow(0)
        self.pl.SetSizer(self.sizer)

        self.Bind(wx.EVT_BUTTON, self.on_button, self.bt)

        self.text.SetValue('\n'.join(self.mobj.cf['defaut']))

        self.Centre()
        self.Show()

    def on_button(self, event):
        self.bt.Disable()
        try:
            self.mobj.pipinstall(self.text.GetValue().split('\n'))
        except Exception as e:
            self.bt.Enable()
            raise e
        else:
            self.bt.Enable()
            print('--- Over ---')


class MainFrameMenuBar(wx.MenuBar):
    def __init__(self, mobj):
        wx.MenuBar.__init__(self)
        self.mobj = mobj
        menumap = {
            '选项': [(wx.ID_SETUP, '设置')]
        }

        self.menus = OrderedDict()
        self.items = OrderedDict()
        for key, val in menumap.items():
            self.menus[key] = wx.Menu()
            for id, text in val:
                self.items[key] = OrderedDict()
                self.items[key][text] = self.menus[key].Append(id, item=text)

        for key, val in self.menus.items():
            self.Append(val, title=key)

        self.Bind(wx.EVT_MENU, lambda e: mobj.setup(), self.items['选项']['设置'])


class SetupWin(wx.Frame):
    def __init__(self, parent, mobj):
        wx.Frame.__init__(self, parent=parent, title='设置', size=(600, 300))
        self.mobj = mobj

        self.pl = wx.Panel(self, size=(600, 300))

        self.check = {}
        self.check['uninstall'] = wx.CheckBox(self.pl, label='我要卸载')
        self.check['-i'] = wx.CheckBox(self.pl, label='使用其它安装源')
        self.text = {}
        self.text['srsaddr'] = (wx.StaticText(self.pl, label='其它安装源'), wx.TextCtrl(self.pl))
        self.bt = wx.Button(self.pl, label='确认', size=(60, 40))

        self.sizer = wx.GridBagSizer(5, 5)
        i = 0
        for i, (key, x) in enumerate(self.check.items()):
            self.sizer.Add(x, pos=(i, 0), span=(1, 2), flag=wx.EXPAND | wx.ALL, border=10)
            x.SetValue(self.mobj.cf[key])
        for i, (key, x) in enumerate(self.text.items(), start=i + 1):
            self.sizer.Add(x[0], pos=(i, 0), span=(1, 1), flag=wx.EXPAND | wx.ALL, border=10)
            self.sizer.Add(x[1], pos=(i, 1), span=(1, 2), flag=wx.EXPAND | wx.ALL, border=10)
            x[1].SetValue(self.mobj.cf[key])

        self.sizer.Add(self.bt, pos=(i + 1, 2), span=(1, 1), flag=wx.ALL, border=10)

        self.sizer.AddGrowableCol(1)

        self.pl.SetSizer(self.sizer)

        self.Bind(wx.EVT_BUTTON, self.confirm, self.bt)

        self.Centre()
        self.Show()

    def confirm(self, event):
        for key, val in self.check.items():
            self.mobj.setcf(key, val.GetValue())
        for key, val in self.text.items():
            self.mobj.setcf(key, val[1].GetValue())
        self.Destroy()



class AlertUserChsePythonWin(wx.Dialog):
    "在注册表中找到多个Python时，提醒用户选择其中一个"

    def __init__(self, parent=None, title='选择需要安装的Python', mainobj=None, items=()):
        wx.Dialog.__init__(self, parent=parent, title=title, size=(500, 200), style=wx.STAY_ON_TOP | wx.CAPTION)
        self.mainobj = mainobj
        self.items = items
        self.SetBackgroundColour(wx.Colour(200, 210, 210))

        self.pl = wx.Panel(self, size=(500, 200))
        self.alerttext = wx.StaticText(self.pl, label='找到多个Python,请选择其中一个:',
                                       style=wx.ALIGN_CENTRE_HORIZONTAL)
        self.choice = wx.Choice(self.pl, choices=items)
        self.bt = wx.Button(self.pl, label='确认', size=(60, 40))

        self.sizer = wx.GridBagSizer(5, 10)
        self.sizer.Add(self.alerttext, pos=(0, 0), span=(1, 2), flag=wx.ALL | wx.EXPAND, border=10)
        self.sizer.Add(self.choice, pos=(1, 0), span=(1, 2), flag=wx.ALL | wx.EXPAND, border=10)
        self.sizer.Add(self.bt, pos=(2, 1), span=(1, 1), flag=wx.ALL, border=5)
        self.sizer.AddGrowableCol(0)
        self.pl.SetSizer(self.sizer)

        self.Bind(wx.EVT_BUTTON, self.on_button, self.bt)

        self.Centre()

    def on_button(self, event):
        text = self.choice.GetStringSelection()
        if text:
            index = self.items.index(text)
            self.EndModal(index)

if __name__ == '__main__':
    autopip = AutoPip()
    autopip.app.MainLoop()
